﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.ApplicationModel.Resources.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.Storage.BulkAccess;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage.FileProperties;

// The data model defined by this file serves as a representative example of a strongly-typed
// model that supports notification when members are added, removed, or modified.  The property
// names chosen coincide with data bindings in the standard item templates.
//
// Applications may use this model as a starting point and build on it, or discard it entirely and
// replace it with something appropriate to their needs.

namespace MetroContractSample.Data
{
  /// <summary>
  /// Base class for <see cref="SampleDataItem"/> and <see cref="SampleDataGroup"/> that
  /// defines properties common to both.
  /// </summary>
  [Windows.Foundation.Metadata.WebHostHidden]
  public abstract class SampleDataCommon : MetroContractSample.Common.BindableBase
  {
    private static Uri _baseUri = new Uri("ms-appx:///");

    public SampleDataCommon(String uniqueId, String title, String subtitle, String description)
    {
      this._uniqueId = uniqueId;
      this._title = title;
      this._subtitle = subtitle;
      this._description = description;
      //this._imagePath = imagePath;
    }

    private string _uniqueId = string.Empty;
    public string UniqueId
    {
      get { return this._uniqueId; }
      set { this.SetProperty(ref this._uniqueId, value); }
    }

    private string _title = string.Empty;
    public string Title
    {
      get { return this._title; }
      set { this.SetProperty(ref this._title, value); }
    }

    private string _subtitle = string.Empty;
    public string Subtitle
    {
      get { return this._subtitle; }
      set { this.SetProperty(ref this._subtitle, value); }
    }

    private string _description = string.Empty;
    public string Description
    {
      get { return this._description; }
      set { this.SetProperty(ref this._description, value); }
    }

    private ImageSource _image = null;
    //private String _imagePath = null;
    public ImageSource Image
    {
      get
      {
        //if (this._image == null && this._imagePath != null)
        //{
        //    this._image = new BitmapImage(new Uri(SampleDataCommon._baseUri, this._imagePath));
        //}
        return this._image;
      }

      set
      {
        //this._imagePath = null;
        this.SetProperty(ref this._image, value);
      }
    }

    //public void SetImage(String path)
    //{
    //    this._image = null;
    //    this._imagePath = path;
    //    this.OnPropertyChanged("Image");
    //}
  }

  /// <summary>
  /// Generic item data model.
  /// </summary>
  public class SampleDataItem : SampleDataCommon, IComparable<SampleDataItem>
  {
    //public SampleDataItem(String uniqueId, String title, String subtitle, String imagePath, String description, String content, SampleDataGroup group)
    //    : base(uniqueId, title, subtitle, imagePath, description)
    //{
    //    this._content = content;
    //    this._group = group;
    //}

    public SampleDataItem(FileInformation fileInfo, SampleDataGroup group)
      : base(fileInfo.Path, fileInfo.Name, fileInfo.Path, CreateDescriptionText(fileInfo))
    {
      this._fileInfo = fileInfo;
      this._content = CreateContentText(fileInfo);
      this._group = group;

      GetThumbnail(fileInfo);
    }


    private static string CreateDescriptionText(FileInformation file)
    {
      var path = file.Path;
      var contentType = file.ContentType;
      DateTimeOffset created = file.DateCreated;
      var fileType = file.FileType;
      DateTimeOffset modified = file.BasicProperties.DateModified;
      ulong size = file.BasicProperties.Size;

      return string.Format(
@"パス: {0}
コンテンツタイプ: {1}
更新日: {2}
サイズ: {3} Bytes",
              path, contentType, modified.ToString(), size.ToString());

    }

    private static string CreateContentText(FileInformation file)
    {
      var props = file.DocumentProperties;
      StringBuilder sb = new StringBuilder();

      if (props.Author.Count > 0)
      {
        sb.Append("Authors: ");
        sb.AppendLine(string.Join(", ", props.Author));
      }
      if (!string.IsNullOrWhiteSpace(props.Title))
      {
        sb.Append("Title: ");
        sb.AppendLine(props.Title);
      }

      return sb.ToString();
    }

    private async void GetThumbnail(FileInformation file)
    {
      using (var thumb = await file.GetThumbnailAsync(ThumbnailMode.SingleItem))
      {
        if (thumb == null)
          return;

        var bmp = new BitmapImage();
        bmp.SetSource(thumb);
        base.Image = bmp;
      }
    }



    private FileInformation _fileInfo = null;
    public FileInformation FileInfo
    {
      get { return this._fileInfo; }
    }

    private string _content = string.Empty;
    public string Content
    {
      get { return this._content; }
      set { this.SetProperty(ref this._content, value); }
    }

    private SampleDataGroup _group;
    public SampleDataGroup Group
    {
      get { return this._group; }
      set { this.SetProperty(ref this._group, value); }
    }



    // IComparer<SampleDataItem>
    public int CompareTo(SampleDataItem other)
    {
      return string.Compare(this.Title, other.Title, StringComparison.CurrentCultureIgnoreCase);
    }
  }

  /// <summary>
  /// Generic group data model.
  /// </summary>
  public class SampleDataGroup : SampleDataCommon
  {
    //public SampleDataGroup(String uniqueId, String title, String subtitle, String imagePath, String description)
    //    : base(uniqueId, title, subtitle, imagePath, description)
    //{
    //}
    public SampleDataGroup(String uniqueId, String title, String subtitle, String description)
      : base(uniqueId, title, subtitle, description)
    {
    }

    private ObservableCollection<SampleDataItem> _items = new ObservableCollection<SampleDataItem>();
    public ObservableCollection<SampleDataItem> Items
    {
      get { return this._items; }
    }
  }

  /// <summary>
  /// Creates a collection of groups and items with hard-coded content.
  /// </summary>
  public sealed class SampleDataSource
  {
    private ObservableCollection<SampleDataGroup> _itemGroups = new ObservableCollection<SampleDataGroup>();
    public ObservableCollection<SampleDataGroup> ItemGroups
    {
      get { return this._itemGroups; }
    }

    public SampleDataSource()
    {

    }



    public bool HasData
    {
      get { return (this.ItemGroups.Count > 0); }
    }

    public IEnumerable<SampleDataItem> FilteredByFilename(string query)
    {
      foreach (var group in this.ItemGroups)
      {
        foreach (var item in group.Items)
        {
          if (item.FileInfo.Name.StartsWith(query, StringComparison.CurrentCultureIgnoreCase))
            yield return item;
        }
      }
    }

    public IEnumerable<SampleDataItem> FilteredByExtension(IEnumerable<string> fileExtensions)
    {
      if (fileExtensions.Count(ext => string.IsNullOrWhiteSpace(ext) || ext == "*") > 0)
      {
        foreach (var group in this.ItemGroups)
          foreach (var item in group.Items)
            yield return item;

        yield break;
      }

      foreach (var group in this.ItemGroups)
      {
        foreach (var item in group.Items)
        {
          var fileName = item.FileInfo.Name;
          foreach (var ext in fileExtensions)
            if (fileName.EndsWith(ext, StringComparison.CurrentCultureIgnoreCase))
              yield return item;
        }
      }
    }

  }
}
